package at.main.android;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Vector;

import android.content.Context;

public class RecordStore {
	
	/** Authorization to allow access to any MIDlet suites. */
	public static int 	AUTHMODE_ANY = 1;
	/** Authorization to allow access only to the current MIDlet suite. */
	public static int 	AUTHMODE_PRIVATE = 0;
	
//	/** Adds the specified RecordListener. */
//	void addRecordListener(RecordListener listener)
    
//	/** Returns an enumeration for traversing a set of records in the record store in an optionally specified order. */
//	RecordEnumeration enumerateRecords(RecordFilter filter, RecordComparator comparator, boolean keepUpdated)

//	/** Returns the last time the record store was modified, in the format used by System.currentTimeMillis(). */
//	long getLastModified()

//	/** Returns the recordId of the next record to be added to the record store. */
//	public int getNextRecordID(){}

//	/** Removes the specified RecordListener. */
//	void removeRecordListener(RecordListener listener)

//	/** Changes the access mode for this RecordStore. */
//	void setMode(int authmode, boolean writable)
    
//	/** Returns the amount of space, in bytes, that the record store occupies. */
//	public int getSize(){}

//	/** Returns the amount of additional room (in bytes) available for this record store to grow. */
//	public int getSizeAvailable(){}

//	/** Each time a record store is modified (by addRecord, setRecord, or deleteRecord methods) its version is incremented. */
//	public int getVersion(){}

	private Vector<byte[]> vec = null;
	private String FILENAME = null;
	private static Vector<RecordStore> vIns = null;
	private static String lst[] = {"vme"};
	
	public void destroy(){
		vec.removeAllElements();
		vIns.removeAllElements();
	}

	private RecordStore(String RecordName){
		FILENAME = RecordName + ".rs";
		load();
		if(vIns == null)
			vIns = new Vector<RecordStore>();
		vIns.addElement(this);
	}
	
	/** Open (and possibly create) a record store associated with the given MIDlet suite. */
	public static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary) {
		if(vIns != null){
			for(int i = 0; i < vIns.size(); i++)
				if(vIns.elementAt(i).getName().equals(recordStoreName))
					return vIns.elementAt(i);
		}
		return new RecordStore(recordStoreName);
	}
	
	/** Open (and possibly create) a record store that can be shared with other MIDlet suites. */
	public static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary, int authmode, boolean writable){
		return openRecordStore(recordStoreName, createIfNecessary);
	}
    
	/** Open a record store associated with the named MIDlet suite. */
	public static RecordStore openRecordStore(String recordStoreName, String vendorName, String suiteName){
		return openRecordStore(recordStoreName, false);
	}

	/** This method is called when the MIDlet requests to have the record store closed. */
	public void closeRecordStore() {
		// nothing to do
	}
	
	/** The record is deleted from the record store. */
	public void deleteRecord(int Index) {
		if(Index >= vec.size())
			return;
		
		vec.removeElementAt(Index);
	}
	
	/** Returns an array of the names of record stores owned by the MIDlet suite. */
	public static String[] listRecordStores() {
		return lst;
	}

	/** Deletes the named record store. */
	public static void deleteRecordStore(String m_rec_store) {
		Static.App.deleteFile(m_rec_store);
	}
	
	// READ ----------------------------------
	/** Returns the number of records currently in the record store. */
	public int getNumRecords() {
		if(vec == null)	return 0;
		return vec.size();
	}

	/** Returns the size (in bytes) of the MIDlet data available in the given record. */
	public int getRecordSize(int recordId) {
		if(vec == null || (recordId >= 0 && recordId < vec.size()))
			return -1;
		return vec.elementAt(recordId).length;
	}

	/** Returns a copy of the data stored in the given record. */
	public byte[] getRecord(int recordId){
		if(vec == null || (recordId >= 0 && recordId < vec.size())){
			return null;
		}
		return vec.elementAt(recordId);
	}
	
	/** Returns the data stored in the given record. */
	public int getRecord(int Index, byte[] arrByte, int iOffset) {
		if(vec == null || (Index >= 0 && Index < vec.size())){
			arrByte = null;
			return 0;
		}
		arrByte = new byte[vec.elementAt(Index).length - iOffset];
		System.arraycopy(vec.elementAt(Index), iOffset, arrByte, 0, arrByte.length);
		return arrByte.length;
	}
	
	/** Returns the name of this RecordStore. */
	public String getName(){
		return FILENAME;
	}
	
	// WRITE ----------------------------------
	/** Adds a new record to the record store. */
	public int addRecord(byte[] arrByte, int iOffset, int count) {
		byte content[] = new byte[count];
		System.arraycopy(arrByte, iOffset, content, 0, count);
		vec.addElement(content);
		save();
		return 1;
	}

	/** Sets the data in the given record to that passed in. */
	public void setRecord(int Index, byte[] arrByte, int iOffset, int count) {
		if(Index >= vec.size())
			return;
		
		System.arraycopy(arrByte, iOffset, vec.elementAt(Index), 0, count);
		
		save();
	}
	
	// PRIVATE ------------------------------------
	public int lenINDEXTAB(){
		return (vec.size() + 1)*4;
	}
	
	private void load(){
		try {
			FileInputStream fis = Static.App.openFileInput(FILENAME);
			
			if(vec == null)
				vec = new Vector<byte[]>();
			
			byte tmp[] = new byte[4];
			fis.read(tmp);
			int offset = 0;
			int val = 0
			| (tmp[offset+0] & 0xFF)
			| ((tmp[offset+1] & 0xFF) << 8)
			| ((tmp[offset+2] & 0xFF) << 16)
			| ((tmp[offset+3] & 0xFF) << 24);
			tmp = null;
			
			int n = val;
			byte arr[] = new byte[n*4];
			fis.read(arr);
			
			for(int i = 0; i < n; i++) {
				val = 0
				| (arr[offset+0] & 0xFF)
				| ((arr[offset+1] & 0xFF) << 8)
				| ((arr[offset+2] & 0xFF) << 16)
				| ((arr[offset+3] & 0xFF) << 24);
				offset += 4;
				
				byte content[] = new byte[val];
				fis.read(content);
				vec.addElement(content);
			}
			
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void save() {
		FileOutputStream fos;
		try {
			fos = Static.App.openFileOutput(FILENAME, Context.MODE_PRIVATE);
			if(vec == null || vec.size() == 0)
				return;
			byte arrByte[] = new byte[lenINDEXTAB()];
			int offset = 0;
			int value = vec.size();
			arrByte[offset+0] = (byte)(value & 0xFF);
			arrByte[offset+1] = (byte)((value >> 8) & 0xFF);
			arrByte[offset+2] = (byte)((value >> 16) & 0xFF);
			arrByte[offset+3] = (byte)((value >> 24) & 0xFF);
			offset += 4;
			for(int i = 0; i < vec.size(); i++){
				value = vec.elementAt(i).length;
				arrByte[offset+0] = (byte)(value & 0xFF);
				arrByte[offset+1] = (byte)((value >> 8) & 0xFF);
				arrByte[offset+2] = (byte)((value >> 16) & 0xFF);
				arrByte[offset+3] = (byte)((value >> 24) & 0xFF);
				offset += 4;
			}
			
			fos.write(arrByte);
			for(int i = 0; i < vec.size(); i++)
				fos.write(vec.elementAt(i));
			
			fos.flush();
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
